﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using Sern.Abstracts.Tracker.DataContracts;

namespace Sern.Abstracts.Tracker.ServiceContracts
{
    /// <summary>
    /// Note the tracker is almost synonymous with job. So tracker is if and only if job. Tracker is just the "physical" or plumbing extension of a job whereas "job" is the logical layer of the tracker.
    /// </summary>
    [ServiceContract]
    public interface ITracker
    {
        /// <summary>
        /// Used to compile the state of the job.
        /// </summary>
        /// <param name="jobId"> </param>
        /// <param name="type"></param>
        /// <param name="keyHash"></param>
        /// <param name="keyRedundancyHash"> </param>
        /// <param name="keyShape"> </param>
        /// <param name="valueShape"></param>
        /// <returns></returns>
        [OperationContract]
        ClientInfo FindActiveClientInfo(Guid jobId, ClientType type, Guid keyHash, Guid keyRedundancyHash, string keyShape, string valueShape);


        /// <summary>
        /// Join the client to the tracker and return its client Id.
        /// </summary>
        /// <param name="jobId"> </param>
        /// <param name="clientId"> </param>
        /// <param name="clientType"></param>
        /// <param name="clientUri"></param>
        /// <param name="keyShape"> </param>
        /// <param name="valueShape">Only to be used for mapper, reducer and collector.</param>
        /// <param name="clientHostUri"> </param>
        [OperationContract]
        void Subscribe(Guid jobId, Guid clientId, ClientType clientType, string clientUri, string keyShape, string valueShape, string clientHostUri);

        /// <summary>
        /// Unsubscribe the given client id from the map reduce network tracker.
        /// </summary>
        /// <param name="clientId"></param>
        [OperationContract]
        void Unsubscribe(Guid clientId);

        /// <summary>
        /// Check if more needs to be sent. It places significant overhead on both the system and collector however, since the result must be grouped by locationId. Not to mention the system will
        /// be working twice as hard. However this will allow the network to "self-heal" in the event of a failure. Also hopefully the end result is fairly small after all the reduction!
        /// </summary>
        /// <param name="jobId"> </param>
        /// <param name="key"> </param>
        /// <param name="redundancyKey"> </param>
        /// <param name="targetClientType"> </param>
        /// <param name="locationId"></param>
        /// <returns></returns>
        [OperationContract]
        bool IsMinimumRedundancySatisfied(Guid jobId, Guid key, Guid redundancyKey, ClientType targetClientType);

        #region This is far too complex for the current scope.

        ///// <summary>
        ///// Get all the feeder (originating) keys that failed
        ///// to process due to an uncaught exception during the map and reduce process.
        ///// </summary>
        ///// <param name="timeOutSpan"> </param>
        ///// <remarks>The receiver can use this information to call "Repush" on the Feeder
        ///// preferrably after all the other job has finished running. Otherwise any notification
        ///// sent the feeder has reached end of batch will be rendered invalid!</remarks>
        ///// <returns></returns>
        //[OperationContract]
        //IEnumerable<Guid> GetTimedOutRootKeys(TimeSpan timeOutSpan);

        #endregion
    }
}
